#include "cpu/exec/template-start.h"

#define instr jmp

static void do_execute() {
	cpu.eip += op_src->val;
	print_asm(str(instr) " %x", cpu.eip + 1 + DATA_BYTE);
}

make_instr_helper(si)
#if DATA_BYTE == 4
make_helper(jmp_rm_l) {
	int len = decode_rm_l(eip + 1);
	cpu.eip = op_src->val - (len + 1);
	print_asm(str(instr) " *%s", op_src->str);
	return len + 1;
}

make_helper(ljmp)
{

	uint32_t new_eip = instr_fetch(cpu.eip + 1, 4);
	uint16_t selector = instr_fetch(cpu.eip + 1 + 4, 2);
	cpu.eip = new_eip;
	cpu.s_reg.cs.selector = selector;
	uint16_t index = cpu.s_reg.cs.selector >> 3;
	Assert((index << 3) <= cpu.gdtr.seg_limit, "Segement Selector Is Out Of The Limit!");
	uint32_t target_desc_addr = cpu.gdtr.base_addr + (index << 3);
	sreg_desc.part1 = lnaddr_read(target_desc_addr, 4);
	sreg_desc.part2 = lnaddr_read(target_desc_addr + 4, 4);
	uint32_t base_addr = 0;
	base_addr |= ((uint32_t)sreg_desc.base_0_15bit);
	base_addr |= ((uint32_t)sreg_desc.base_16_23bit) << 16;
	base_addr |= ((uint32_t)sreg_desc.base_24_31bit) << 24;
	cpu.s_reg.cs.seg_base = base_addr;
	uint32_t seg_limit = 0;
	seg_limit |= ((uint32_t)sreg_desc.limit_0_15bit);
	seg_limit |= ((uint32_t)sreg_desc.limit_16_19bit) << 16;
	seg_limit |= ((uint32_t)0xfff) << 24;
	cpu.s_reg.cs.seg_limit = seg_limit;
	if (sreg_desc.g == 1) {
		cpu.s_reg.cs.seg_limit <<= 12;
	}
	print_asm("ljump");
	return 0;	
}
#endif
#include "cpu/exec/template-end.h"
